const std = @import("std");
const builtin = @import("builtin");

// zig build-exe src/main.zig

// zig build
// ./zig-out/bin/ch004

// zig  run  src/main.zig
fn read_file(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
    const file = try std.fs.cwd().openFile(path, .{});
    defer file.close();
    return try file.reader().readAllAlloc(allocator, std.math.maxInt(usize));
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    // try stdout.print("Hello, {s}!\n", .{"world"});

    // var age: u8 = 24;
    // age = 25;
    // try stdout.print( "{d}\n",.{age});
    // std.debug.print("{d}\n", .{age + 2});
    // try stdout.print("Hello, {s}!\n", age);

    // const ns = [4]u8{1,2,3,4};
    // const ls = [_]f64{1.1,2.2,3.3,4.4};

    // 如果变量定义了后面没有使用，这里用一下，让编译通过
    // _ = ns;
    // error: pointless discard of local constant
    // _ = ls;

    // const ns = [4]u8{48, 24, 12, 6};
    // 取数组中的元素
    // try stdout.print("{d}\n", .{ ls[2] });

    // 数组切片
    // const sl = ns[1..3];
    // _ = sl;

    // 数组长度
    // try stdout.print("{d}\n", .{ ns.len });

    // 切片方法
    // const ns = [4]u8{48, 24, 12, 6};
    // const sl = ns[1..];
    // _ = sl;

    // 数组打印输出
    // try stdout.print("{any}\n", .{sl});

    // const a = [_]u8{1,2,3};
    // const b = [_]u8{4,5};
    // const c = a ++ b;
    // try stdout.print("{any}\n", .{c});

    // const a = [_]u8{1,2,3};
    // const c = a ** 2;
    // try stdout.print("{any}\n", .{c});

    // const arr1 = [10]u64 {
    // 1, 2, 3, 4, 5,
    // 6, 7, 8, 9, 10
    // };
    // // This slice has a compile-time known range.
    // // Because we know both the start and end of the range.
    // const slice = arr1[1..5];
    // try stdout.print("{any}\n", .{slice});

    // 1.6.4切片的运行时与编译时已知长度
    // var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    // const allocator = gpa.allocator();
    // const path = "./src/root.zig";
    // const file_contents = try read_file(allocator, path);
    // const slice = file_contents[0..file_contents.len];
    // try stdout.print("{any}\n", .{slice});

    // 1.7块和作用域
    // var y: i32 = 123;
    // const x = add_one: {
    //     y += 1;
    //     break :add_one y;
    // };
    // if (x == 124 and y == 124) {
    //     try stdout.print("Hey!", .{});
    // }

    // 1.8字符串在 Zig 中如何工作？
    // const string_object = "This is an example of string literal in Zig";
    // try stdout.print("{d}\n", .{string_object.len});

    // const bytes = [_]u8{0x48, 0x65, 0x6C, 0x6C, 0x6F};
    // try stdout.print("{s}\n", .{bytes});

    // 1.8.2遍历字符串
    // const string_object = "This is an example";
    // try stdout.print("Bytes that represents the string object: ", .{});
    // for (string_object) |byte| {
    //     try stdout.print("{X} ", .{byte});
    // }
    // try stdout.print("\n", .{});

    // 1.8.4字节与unicode点
    // 1.8.5一些有用的字符串函数
    const name: []const u8 = "Pedro";
    try stdout.print("{any}\n", .{std.mem.eql(u8, name, "Pedro")});
}

fn addFive(x: u32) u32 {
    return x + 5;
}

test "function" {
    const y = addFive(0);
    try expect(@TypeOf(y) == u32);
    try expect(y == 5);
}

const expect = @import("std").testing.expect;

test "for" {
    //character literals are equivalent to integer literals
    const string = [_]u8{ 'a', 'b', 'c' };

    for (string, 0..) |character, index| {
        _ = character;
        _ = index;
    }

    for (string) |character| {
        _ = character;
    }

    for (string, 0..) |_, index| {
        _ = index;
    }

    for (string) |_| {}
}

test "multi defer" {
    var x: f32 = 5;
    {
        defer x += 2;
        defer x /= 2;
    }
    try expect(x == 4.5);
}
